
#ifndef __URL_H__
#define __URL_H__

#include <cstdio>
#include <string>
#include <map>


namespace URI
{

// Note:
// I don't know is it right.
std::string encode_string(const std::string& value)
{
	char buffer[8];
	std::string encoded;
	char c;
	for(std::string::size_type i=0; i<value.length(); i++)
	{
		c = value[i];
		if( ('a'<=c && c<='z') || ('A'<=c && c<='Z') || ('0'<=c && c<='9') )
		{
			encoded += c;
		}
		else
		{
			std::sprintf(buffer, "%%%02X", c&0xFF);
			encoded += buffer;
		}
	}
	return encoded;
}

std::string encode_data(const std::map<std::string, std::string>& form_data)
{
	if(form_data.empty())
		return "";
	std::string line;
	std::map<std::string, std::string>::const_iterator i = form_data.begin();
	//Bad code
	//too many temp objects
	line += encode_string((*i).first) + "=" + encode_string((*i).second);
	i++;
	for(; i!=form_data.end(); i++)
	{
		line += "&";
		line += encode_string((*i).first);
		line += "=";
		line += encode_string((*i).second);
	}
	return line;
}

class URL
{
public:
	URL(const std::string& raw_url):url(raw_url), flag(1) { split(); };
//	URL(const char* raw_url):url(raw_url), flag(1) { split(); };
//	URL(const URL&);
	
	std::string get_url() const {return url;}
	std::string get_host() const {return host;}
	std::string get_file() const {return file+query_line;}
	bool is_ok() const {return flag;};
	std::string get_error() const {return error;}
	std::string to_string() const {return "http://"+host+file+query_line;}

	void query_form(const std::string& k, const std::string& v)
	{
		query_line = "?";
		query_line += encode_string(k);
		query_line += "=";
		query_line += encode_string(v);
	}
	
	void query_form(const std::string& k1, const std::string& v1,
	                const std::string& k2, const std::string& v2)
	{
		query_line = "?";
		query_line += encode_string(k1);
		query_line += "=";
		query_line += encode_string(v1);
		query_line += "&";
		query_line += encode_string(k2);
		query_line += "=";
		query_line += encode_string(v2);
	}
	
	void query_form(const std::string& k1, const std::string& v1,
	                const std::string& k2, const std::string& v2,
	                const std::string& k3, const std::string& v3)
	{
		query_line = "?";
		query_line += encode_string(k1);
		query_line += "=";
		query_line += encode_string(v1);
		query_line += "&";
		query_line += encode_string(k2);
		query_line += "=";
		query_line += encode_string(v2);
		query_line += "&";
		query_line += encode_string(k3);
		query_line += "=";
		query_line += encode_string(v3);
	}
	
	void query_form(const std::string& k1, const std::string& v1,
	                const std::string& k2, const std::string& v2,
	                const std::string& k3, const std::string& v3,
	                const std::string& k4, const std::string& v4)
	{
		query_line = "?";
		query_line += encode_string(k1);
		query_line += "=";
		query_line += encode_string(v1);
		query_line += "&";
		query_line += encode_string(k2);
		query_line += "=";
		query_line += encode_string(v2);
		query_line += "&";
		query_line += encode_string(k3);
		query_line += "=";
		query_line += encode_string(v3);
		query_line += "&";
		query_line += encode_string(k4);
		query_line += "=";
		query_line += encode_string(v4);
	}
	
	void query_form(const std::map<std::string, std::string>& form)
	{
		if(form.empty())
			return;
		query_line = "?";
		query_line += encode_data(form);
	}

	operator std::string() const
	{
		return to_string();
	}
	
private:
	std::string url;
	std::string host;
	std::string file;
	std::string query_line;
	std::string error;
	bool flag;
	
	void split()
	{
		if( url.length() > 6
			&& (url[0]=='H'||url[0]=='h')
			&& (url[1]=='T'||url[1]=='t') 
			&& (url[2]=='T'||url[2]=='t')
			&& (url[3]=='P'||url[3]=='p')
			&& url[4]==':' && url[5]=='/' && url[6]=='/')
		{
			host = url.substr(7);
		}
		else if (url.find("://")!=std::string::npos)
		{
			error = "Unspported protocol";
			return;
		}
		else
		{
			host = url;
		}

		std::string::size_type i = host.find('/');
		if(i!=std::string::npos)
		{
			file = host.substr(i);
			host = host.substr(0, i);
		}
		else
		{
			file = "/";
		}
	}
	
};



}

#endif

